package model

import (
	"database/sql/driver"
	"fmt"
	"strings"
	"time"

	"gorm.io/gorm"
)

// --- Order Status Constants ---

// Inbound Order Status
const (
	StatusInboundCancelled      = 0 // 已取消
	StatusInboundWaitingReceive = 1 // 待收货
	StatusInboundWaitingPutaway = 2 // 待上架
	StatusInboundCompleted      = 3 // 已完成
)

// Outbound Order Status
const (
	StatusOutboundCancelled       = 0 // 已取消
	StatusOutboundWaitingPicking  = 1 // 待拣货
	StatusOutboundWaitingShipping = 2 // 待发货
	StatusOutboundCompleted       = 3 // 已完成
)

// GetOutboundStatusText 返回出库单状态的文本描述
func GetOutboundStatusText(status int) string {
	switch status {
	case StatusOutboundCancelled:
		return "已取消"
	case StatusOutboundWaitingPicking:
		return "待拣货"
	case StatusOutboundWaitingShipping:
		return "待发货"
	case StatusOutboundCompleted:
		return "已完成"
	default:
		return fmt.Sprintf("未知状态 (%d)", status)
	}
}

// Inventory 库存
// @Description 库存信息
// @Success 200 {object} common.Response{data=Inventory} "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /inventory [get]
type Inventory struct {
	ID          uint           `json:"id" gorm:"primarykey"`
	CreatedAt   time.Time      `json:"created_at"`
	UpdatedAt   time.Time      `json:"updated_at"`
	DeletedAt   gorm.DeletedAt `json:"-" gorm:"index"`
	CargoID     uint           `json:"cargo_id"`                                // 货物ID
	Cargo       *Cargo         `json:"cargo" gorm:"foreignKey:CargoID"`         // 货物信息
	WarehouseID uint           `json:"warehouse_id"`                            // 仓库ID
	Warehouse   *Warehouse     `json:"warehouse" gorm:"foreignKey:WarehouseID"` // 仓库信息
	LocationID  uint           `json:"location_id"`                             // 货位ID
	Location    *Location      `json:"location" gorm:"foreignKey:LocationID"`   // 货位信息
	Quantity    float64        `json:"quantity" gorm:"not null;default:0"`      // 库存数量
	LockStock   float64        `json:"lock_stock" gorm:"default:0"`             // 锁定库存
	MinStock    float64        `json:"min_stock" gorm:"default:0"`              // 最小库存
	MaxStock    float64        `json:"max_stock" gorm:"default:0"`              // 最大库存
	Status      int            `json:"status" gorm:"not null;default:1"`        // 状态（1:正常 0:禁用）

	// 非数据库字段，仅用于API响应
	BatchNo        string     `json:"batch_no" gorm:"-"`        // 批次号（非数据库字段）
	ProductionDate *time.Time `json:"production_date" gorm:"-"` // 生产日期（非数据库字段）
	ExpiryDate     *time.Time `json:"expiry_date" gorm:"-"`     // 过期日期（非数据库字段）

	// 添加平铺的字段，用于前端显示
	CargoCode     string `json:"cargo_code" gorm:"-"`     // 货物编码（平铺，非数据库字段）
	CargoName     string `json:"cargo_name" gorm:"-"`     // 货物名称（平铺，非数据库字段）
	CategoryName  string `json:"category_name" gorm:"-"`  // 分类名称（平铺，非数据库字段）
	SupplierName  string `json:"supplier_name" gorm:"-"`  // 供应商名称（平铺，非数据库字段）
	WarehouseName string `json:"warehouse_name" gorm:"-"` // 仓库名称（平铺，非数据库字段）
	LocationCode  string `json:"location_code" gorm:"-"`  // 库位编码（平铺，非数据库字段）
	Unit          string `json:"unit" gorm:"-"`           // 单位（平铺，非数据库字段）
}

// TableName 表名
func (Inventory) TableName() string {
	return "inventories"
}

// InventoryAdjustment 库存调整记录
type InventoryAdjustment struct {
	ID          uint      `json:"id" gorm:"primarykey"`
	CargoID     uint      `json:"cargo_id" gorm:"not null"` // 货物ID
	Quantity    int       `json:"quantity" gorm:"not null"`
	Reason      string    `json:"reason" gorm:"not null"`
	OperatorID  uint      `json:"operator_id" gorm:"not null"`
	BeforeStock int       `json:"before_stock" gorm:"not null"`
	AfterStock  int       `json:"after_stock" gorm:"not null"`
	AdjustedAt  time.Time `json:"adjusted_at" gorm:"not null"`
	CreatedAt   time.Time `json:"created_at"`
	UpdatedAt   time.Time `json:"updated_at"`
}

// TableName 表名
func (InventoryAdjustment) TableName() string {
	return "inventory_adjustments"
}

// InboundOrder 入库单
type InboundOrder struct {
	ID            uint                `json:"id" gorm:"primarykey"`
	Code          string              `json:"code" gorm:"type:varchar(50);uniqueIndex;not null"` // 入库单号
	Type          int                 `json:"type" gorm:"not null"`                              // 入库类型（1:采购入库 2:退货入库 3:其他入库）
	WarehouseID   uint                `json:"warehouse_id" gorm:"not null"`                      // 仓库ID
	SupplierID    *uint               `json:"supplier_id"`                                       // 供应商ID
	ExpectedTime  *time.Time          `json:"expected_time"`                                     // 预计到货时间
	OrderNo       string              `json:"order_no"`                                          // 关联订单号
	Note          string              `json:"note"`                                              // 备注
	Status        int                 `json:"status" gorm:"not null;default:1;index"`            // 状态 (见 StatusInbound... 常量)
	UserID        uint                `json:"user_id" gorm:"not null"`                           // 创建人ID
	ApproveUserID *uint               `json:"approve_user_id"`                                   // 审核人ID
	ApproveTime   *time.Time          `json:"approve_time"`                                      // 审核时间 (改为指针)
	ApproveNote   string              `json:"approve_note"`                                      // 审核备注
	ReceiveUserID *uint               `json:"receive_user_id"`                                   // 收货人ID
	ReceiveTime   *time.Time          `json:"receive_time"`                                      // 收货时间
	PutawayUserID *uint               `json:"putaway_user_id"`                                   // 上架人ID
	PutawayTime   *time.Time          `json:"putaway_time"`                                      // 上架完成时间
	CancelUserID  *uint               `json:"cancel_user_id"`                                    // 取消人ID
	CancelTime    *time.Time          `json:"cancel_time"`                                       // 取消时间
	Items         []*InboundOrderItem `json:"items" gorm:"foreignKey:InboundOrderID"`            // 入库商品列表
	CreatedAt     time.Time           `json:"created_at"`
	UpdatedAt     time.Time           `json:"updated_at"`
	DeletedAt     gorm.DeletedAt      `json:"-" gorm:"index"`

	User        *User      `json:"user"`                                         // 创建人
	ApproveUser *User      `json:"approve_user" gorm:"foreignKey:ApproveUserID"` // 审核人 (指定外键)
	ReceiveUser *User      `json:"receive_user" gorm:"foreignKey:ReceiveUserID"` // 收货人 (新增)
	PutawayUser *User      `json:"putaway_user" gorm:"foreignKey:PutawayUserID"` // 上架人 (新增)
	CancelUser  *User      `json:"cancel_user" gorm:"foreignKey:CancelUserID"`   // 取消人 (新增)
	Supplier    *Supplier  `json:"supplier" gorm:"foreignKey:SupplierID"`        // 供应商 (添加 GORM 标签)
	Warehouse   *Warehouse `json:"warehouse" gorm:"foreignKey:WarehouseID"`      // 仓库 (添加 GORM 标签)
}

// InboundOrderItem 入库单明细
type InboundOrderItem struct {
	ID               uint           `json:"id" gorm:"primarykey"`
	InboundOrderID   uint           `json:"inbound_order_id" gorm:"index;not null"` // 入库单ID
	CargoID          uint           `json:"cargo_id" gorm:"not null"`               // 货物ID
	Quantity         float64        `json:"quantity" gorm:"not null"`               // 应收数量
	ReceivedQuantity float64        `json:"received_quantity" gorm:"default:0"`     // 实收数量
	PutawayQuantity  float64        `json:"putaway_quantity" gorm:"default:0"`      // 已上架数量
	UnitPrice        float64        `json:"unit_price"`                             // 单价 (允许为空或0)
	BatchNo          string         `json:"batch_no" gorm:"size:50"`                // 批次号
	ProductionDate   *time.Time     `json:"production_date"`                        // 生产日期
	ExpiryDate       *time.Time     `json:"expiry_date"`                            // 有效期至
	LocationID       *uint          `json:"location_id"`                            // 上架库位ID
	Note             string         `json:"note"`                                   // 备注
	CreatedAt        time.Time      `json:"created_at"`
	UpdatedAt        time.Time      `json:"updated_at"`
	DeletedAt        gorm.DeletedAt `json:"-" gorm:"index"`

	Cargo    *Cargo    `json:"cargo"`                                 // 货物信息
	Location *Location `json:"location" gorm:"foreignKey:LocationID"` // 上架库位信息
}

// OutboundOrder 出库单
type OutboundOrder struct {
	ID            uint                 `json:"id" gorm:"primarykey"`
	Code          string               `json:"code" gorm:"type:varchar(50);uniqueIndex;not null"` // 出库单号
	Type          int                  `json:"type" gorm:"not null"`                              // 出库类型（1:销售出库 2:领用出库 3:调拨出库 4:退货出库 5:其他出库）
	WarehouseID   uint                 `json:"warehouse_id" gorm:"not null"`                      // 仓库ID
	CustomerID    *uint                `json:"customer_id"`                                       // 客户ID
	OrderNo       string               `json:"order_no"`                                          // 关联订单号
	Note          string               `json:"note"`                                              // 备注
	Status        int                  `json:"status" gorm:"not null;default:1;index"`            // 状态 (见 StatusOutbound... 常量)
	UserID        uint                 `json:"user_id" gorm:"not null"`                           // 创建人ID
	ApproveUserID *uint                `json:"approve_user_id"`                                   // 审核人ID
	ApproveTime   *time.Time           `json:"approve_time"`                                      // 审核时间 (改为指针)
	ApproveNote   string               `json:"approve_note"`                                      // 审核备注
	PickUserID    *uint                `json:"pick_user_id"`                                      // 拣货员ID
	PickTime      *time.Time           `json:"pick_time"`                                         // 拣货完成时间
	ShipUserID    *uint                `json:"ship_user_id"`                                      // 发货员ID
	ShipTime      *time.Time           `json:"ship_time"`                                         // 发货时间 (可能是第一次或最后一次，取决于更新逻辑)
	CancelUserID  *uint                `json:"cancel_user_id"`                                    // 取消人ID
	CancelTime    *time.Time           `json:"cancel_time"`                                       // 取消时间
	Items         []*OutboundOrderItem `json:"items" gorm:"foreignKey:OutboundOrderID"`           // 出库商品列表
	CreatedAt     time.Time            `json:"created_at"`
	UpdatedAt     time.Time            `json:"updated_at"`
	DeletedAt     gorm.DeletedAt       `json:"-" gorm:"index"`

	// --- 新增：最后一次发货信息 ---
	LastTrackingNumber string   `json:"last_tracking_number" gorm:"size:100"` // 最后物流单号
	LastCarrier        string   `json:"last_carrier" gorm:"size:100"`         // 最后承运商
	LastShippingCost   *float64 `json:"last_shipping_cost"`                   // 最后运费
	LastShippingNote   string   `json:"last_shipping_note"`                   // 最后发货备注
	// ShipTime 字段已存在，可用于表示最后发货时间

	User        *User      `json:"user"`                                         // 创建人
	ApproveUser *User      `json:"approve_user" gorm:"foreignKey:ApproveUserID"` // 审核人
	PickUser    *User      `json:"pick_user" gorm:"foreignKey:PickUserID"`       // 拣货员 (新增)
	ShipUser    *User      `json:"ship_user" gorm:"foreignKey:ShipUserID"`       // 发货员 (新增)
	CancelUser  *User      `json:"cancel_user" gorm:"foreignKey:CancelUserID"`   // 取消人 (新增)
	Customer    *Customer  `json:"customer"`                                     // 客户
	Warehouse   *Warehouse `json:"warehouse"`                                    // 仓库
}

// OutboundOrderItem 出库单明细
type OutboundOrderItem struct {
	ID              uint           `json:"id" gorm:"primarykey"`
	OutboundOrderID uint           `json:"outbound_order_id" gorm:"index;not null"` // 出库单ID
	CargoID         uint           `json:"cargo_id" gorm:"not null"`                // 货物ID
	Quantity        float64        `json:"quantity" gorm:"not null"`                // 应出数量
	PickedQuantity  float64        `json:"picked_quantity" gorm:"default:0"`        // 已拣数量
	ShippedQuantity float64        `json:"shipped_quantity" gorm:"default:0"`       // 已发数量
	UnitPrice       float64        `json:"unit_price"`                              // 单价 (允许为空或0)
	BatchNo         string         `json:"batch_no" gorm:"size:50"`                 // 批次号 (出库时可能需要指定批次)
	LocationID      *uint          `json:"location_id"`                             // 拣货库位ID
	Note            string         `json:"note"`                                    // 备注
	CreatedAt       time.Time      `json:"created_at"`
	UpdatedAt       time.Time      `json:"updated_at"`
	DeletedAt       gorm.DeletedAt `json:"-" gorm:"index"`

	Cargo    *Cargo    `json:"cargo"`                                 // 货物信息
	Location *Location `json:"location" gorm:"foreignKey:LocationID"` // 拣货库位信息
}

// InventoryLog 库存日志
type InventoryLog struct {
	ID          uint           `json:"id" gorm:"primarykey"`
	CargoID     uint           `json:"cargo_id"`                                // 货物ID
	Cargo       *Cargo         `json:"cargo" gorm:"foreignKey:CargoID"`         // 货物信息
	WarehouseID uint           `json:"warehouse_id"`                            // 仓库ID
	Warehouse   *Warehouse     `json:"warehouse" gorm:"foreignKey:WarehouseID"` // 仓库信息
	LocationID  uint           `json:"location_id"`                             // 货位ID
	Location    *Location      `json:"location" gorm:"foreignKey:LocationID"`   // 货位信息
	Type        string         `json:"type" gorm:"size:20;not null"`            // 类型（in:入库 out:出库 adjust:调整）
	Quantity    int            `json:"quantity" gorm:"not null"`                // 变动数量
	BeforeStock int            `json:"before_stock"`                            // 变动前库存
	AfterStock  int            `json:"after_stock"`                             // 变动后库存
	OrderType   string         `json:"order_type" gorm:"size:20"`               // 单据类型（inbound:入库单 outbound:出库单）
	OrderID     uint           `json:"order_id"`                                // 单据ID
	OperatorID  uint           `json:"operator_id"`                             // 操作人ID
	Operator    *User          `json:"operator" gorm:"foreignKey:OperatorID"`   // 操作人信息
	Remark      string         `json:"remark" gorm:"size:500"`                  // 备注
	CreatedAt   time.Time      `json:"created_at"`
	UpdatedAt   time.Time      `json:"updated_at"`
	DeletedAt   gorm.DeletedAt `json:"-" gorm:"index"`
}

// TableName 表名
func (InventoryLog) TableName() string {
	return "inventory_logs"
}

// InventoryCheck 库存盘点单
type InventoryCheck struct {
	ID             uint                  `json:"id" gorm:"primarykey"`
	Code           string                `json:"code" gorm:"uniqueIndex;not null"` // 盘点单号
	WarehouseID    uint                  `json:"warehouse_id" gorm:"not null"`     // 仓库ID
	Warehouse      *Warehouse            `json:"warehouse" gorm:"foreignKey:WarehouseID"`
	Status         int                   `json:"status" gorm:"not null;default:1"` // 状态（1:待盘点 2:已完成）
	UserID         uint                  `json:"user_id" gorm:"not null"`          // 创建人ID
	User           *User                 `json:"user" gorm:"foreignKey:UserID"`
	CompleteUserID *uint                 `json:"complete_user_id"` // 完成人ID
	CompleteUser   *User                 `json:"complete_user" gorm:"foreignKey:CompleteUserID"`
	CompleteTime   time.Time             `json:"complete_time"` // 完成时间
	Note           string                `json:"note"`          // 备注
	Items          []*InventoryCheckItem `json:"items"`         // 盘点明细
	CreatedAt      time.Time             `json:"created_at"`
	UpdatedAt      time.Time             `json:"updated_at"`
	DeletedAt      gorm.DeletedAt        `json:"-" gorm:"index"`
}

// TableName 表名
func (InventoryCheck) TableName() string {
	return "inventory_checks"
}

// InventoryCheckItem 库存盘点明细
type InventoryCheckItem struct {
	ID               uint           `json:"id" gorm:"primarykey"`
	InventoryCheckID uint           `json:"inventory_check_id" gorm:"index;not null"` // 盘点单ID
	CargoID          uint           `json:"cargo_id" gorm:"not null"`                 // 货物ID
	Cargo            *Cargo         `json:"cargo" gorm:"foreignKey:CargoID"`          // 货物信息
	LocationID       uint           `json:"location_id"`                              // 货位ID
	Location         *Location      `json:"location" gorm:"foreignKey:LocationID"`
	BookQty          float64        `json:"book_qty" gorm:"not null"`         // 账面数量
	CheckQty         float64        `json:"check_qty" gorm:"not null"`        // 盘点数量
	DiffQty          float64        `json:"diff_qty" gorm:"not null"`         // 差异数量
	Status           int            `json:"status" gorm:"not null;default:1"` // 状态（1:待盘点 2:已盘点）
	Note             string         `json:"note"`                             // 备注
	CreatedAt        time.Time      `json:"created_at"`
	UpdatedAt        time.Time      `json:"updated_at"`
	DeletedAt        gorm.DeletedAt `json:"-" gorm:"index"`
}

// TableName 设置模型对应的数据库表名
func (InventoryCheckItem) TableName() string {
	return "inventory_check_items"
}

// InventoryHistory 库存历史记录
type InventoryHistory struct {
	ID          uint       `json:"id" gorm:"primary_key"`
	CargoID     uint       `json:"cargo_id"`                        // 货物ID
	Cargo       *Cargo     `json:"cargo" gorm:"foreignKey:CargoID"` // 货物信息 (使用指针避免循环引用问题)
	WarehouseID uint       `json:"warehouse_id"`
	Warehouse   *Warehouse `json:"warehouse" gorm:"foreignKey:WarehouseID"`
	LocationID  uint       `json:"location_id"`
	Location    *Location  `json:"location" gorm:"foreignKey:LocationID"`
	Type        string     `json:"type"`       // 变动类型 (e.g., INBOUND, OUTBOUND, ADJUSTMENT)
	Quantity    float64    `json:"quantity"`   // 变动数量 (正数表示增加, 负数表示减少)
	BeforeQty   float64    `json:"before_qty"` // 变动前数量
	AfterQty    float64    `json:"after_qty"`  // 变动后数量
	OrderID     *uint      `json:"order_id"`   // 关联单据ID (入库单, 出库单等)
	OrderType   *string    `json:"order_type"` // 关联单据类型
	UserID      uint       `json:"user_id"`    // 操作用户ID
	User        *User      `json:"user" gorm:"foreignKey:UserID"`
	Remark      string     `json:"remark"`    // 备注
	Timestamp   time.Time  `json:"timestamp"` // 时间戳
}

// TableName 设置模型对应的数据库表名
func (InventoryHistory) TableName() string {
	return "inventory_histories"
}

// InventoryStatus 库存状态（自定义查询结果）
type InventoryStatus struct {
	CargoID       uint    `json:"cargo_id"`       // 货物ID
	CargoName     string  `json:"cargo_name"`     // 货物名称
	TotalQuantity float64 `json:"total_quantity"` // 总库存
	AvailableQty  float64 `json:"available_qty"`  // 可用库存
	LockedQty     float64 `json:"locked_qty"`     // 锁定库存
}

// --- Custom Types for Date Handling ---

// DateOnly is a custom type to handle 'YYYY-MM-DD' date format for JSON and DB.
// It embeds time.Time but overrides JSON marshalling/unmarshalling and DB scanning/valuing.
type DateOnly struct {
	time.Time
}

const dateOnlyLayout = "2006-01-02" // Go's reference layout for YYYY-MM-DD

// UnmarshalJSON implements the json.Unmarshaler interface.
func (d *DateOnly) UnmarshalJSON(b []byte) error {
	s := strings.Trim(string(b), `"`)
	if s == "null" || s == "" {
		return nil
	}
	parsedTime, err := time.Parse(dateOnlyLayout, s)
	if err != nil {
		// Attempt to parse full timestamp as fallback, in case frontend sends it
		parsedTimeFallback, errFallback := time.Parse(time.RFC3339Nano, s)
		if errFallback != nil {
			return fmt.Errorf("parsing date %q: %v, fallback RFC3339Nano error: %v", s, err, errFallback)
		}
		parsedTime = parsedTimeFallback // Use the fallback result if successful
		// No error if fallback worked
		err = nil
	}
	*d = DateOnly{parsedTime}
	return err
}

// MarshalJSON implements the json.Marshaler interface.
func (d DateOnly) MarshalJSON() ([]byte, error) {
	if d.IsZero() {
		return []byte("null"), nil
	}
	return []byte(fmt.Sprintf(`"%s"`, d.Format(dateOnlyLayout))),
		nil
}

// Value implements the driver.Valuer interface.
func (d DateOnly) Value() (driver.Value, error) {
	if d.IsZero() {
		return nil, nil
	}
	// Store only the date part in the database
	return d.Format(dateOnlyLayout), nil
}

// Scan implements the sql.Scanner interface.
func (d *DateOnly) Scan(value interface{}) error {
	if value == nil {
		*d = DateOnly{}
		return nil
	}
	t, ok := value.(time.Time) // GORM might read it as time.Time
	if ok {
		*d = DateOnly{t}
		return nil
	}
	s, ok := value.([]byte) // Or as bytes/string
	if ok {
		parsedTime, err := time.Parse(dateOnlyLayout, string(s))
		if err != nil {
			// Fallback for full timestamp from DB?
			parsedTimeFallback, errFallback := time.Parse(time.RFC3339Nano, string(s))
			if errFallback != nil {
				// Try common DB timestamp format
				parsedTimeFallback2, errFallback2 := time.Parse("2006-01-02 15:04:05", string(s))
				if errFallback2 != nil {
					return fmt.Errorf("scanning date %q: %v, fallback RFC3339: %v, fallback DB format: %v", string(s), err, errFallback, errFallback2)
				}
				parsedTime = parsedTimeFallback2
			} else {
				parsedTime = parsedTimeFallback
			}
			err = nil // Clear error if fallback worked
		}
		*d = DateOnly{parsedTime}
		return err
	}
	return fmt.Errorf("could not scan type %T into DateOnly", value)
}

// InventoryBatch 库存批次信息
type InventoryBatch struct {
	ID             uint           `json:"id" gorm:"primarykey"`
	CreatedAt      time.Time      `json:"created_at"`
	UpdatedAt      time.Time      `json:"updated_at"`
	DeletedAt      gorm.DeletedAt `json:"-" gorm:"index"`
	InventoryID    uint           `json:"inventory_id" gorm:"index;not null"` // 库存ID
	BatchNo        string         `json:"batch_no" gorm:"size:50;not null"`   // 批次号
	Quantity       float64        `json:"quantity" gorm:"not null;default:0"` // 批次数量
	ProductionDate *time.Time     `json:"production_date"`                    // 生产日期
	ExpiryDate     *time.Time     `json:"expiry_date"`                        // 到期日期
	SupplierID     *uint          `json:"supplier_id"`                        // 供应商ID
	InboundOrderID *uint          `json:"inbound_order_id" gorm:"index"`      // 入库单ID
	Status         int            `json:"status" gorm:"not null;default:1"`   // 状态（1:正常 0:禁用）
	CreatedBy      uint           `json:"created_by" gorm:"not null"`         // 创建人ID
	UpdatedBy      uint           `json:"updated_by" gorm:"not null"`         // 更新人ID
	Remark         string         `json:"remark" gorm:"size:500"`             // 备注
}

// TableName 表名
func (InventoryBatch) TableName() string {
	return "wms_inventory_batches"
}

// GetInboundOrderStatusText 获取入库单状态文本
func GetInboundOrderStatusText(status int) string {
	switch status {
	case StatusInboundCancelled: // 0
		return "已取消"
	case StatusInboundWaitingReceive: // 1
		return "待收货"
	case StatusInboundWaitingPutaway: // 2
		return "待上架"
	case StatusInboundCompleted: // 3
		return "已完成"
	default:
		return "未知状态"
	}
}
